package data.join.com.network;

import android.app.Application;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import data.join.com.utils.MyLog;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.BufferedSink;
import okio.GzipSink;
import okio.Okio;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by hefuyi on 16/8/16.
 */

public class RetrofitManager {

    public static class Config {
        public static final int HTTP_CACHE_SIZE = 20 * 1024 * 1024;
        public static final int HTTP_CONNECT_TIMEOUT = 15 * 1000;
        public static final int HTTP_READ_TIMEOUT = 15 * 1000;
    }

    private static RetrofitManager retrofitManager;

    private String Token = null;

    private ApiService mApiService;

    private RetrofitManager(){
        mApiService = getRetrofit().create(ApiService.class);
    }

    public static RetrofitManager getInstance(){
        if(retrofitManager == null){
            retrofitManager = new RetrofitManager();
        }
        return retrofitManager;
    }

    public static ApiService getApiService(){
        return getInstance().mApiService;
    }

    private Retrofit getRetrofit(){
        String startUrl = "https://basket.xpcar.cn/";

        MyLog.D("getRetrofit startUrl = "+startUrl);

        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(Config.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                .readTimeout(Config.HTTP_READ_TIMEOUT, TimeUnit.MILLISECONDS)
//                .addInterceptor(getTokenInterceptor())
                .addInterceptor(new HttpLoggingInterceptor().setLevel(MyLog.isDebug?HttpLoggingInterceptor.Level.BODY:HttpLoggingInterceptor.Level.NONE))
//                .addNetworkInterceptor(new CacheInterceptor(application))
//                .addInterceptor(new GzipRequestInterceptor())
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(startUrl)
                .client(okHttpClient)
                .addConverterFactory(gsonConverterFactory)
                .build();

        return retrofit;
    }

    private Interceptor getTokenInterceptor(){
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();

                if(TextUtils.isEmpty(getToken()) == false) {
                    request = request.newBuilder()
                            .addHeader("Token", getToken())
                            .addHeader("Content-Type", "application/json")
                            .build();
                    //MyLog.D("getTokenInterceptor getToken="+getToken());
                }else{
                    MyLog.D("getTokenInterceptor getToken is NULL");
                }
                return chain.proceed(request);
            }
        };
    }

    public void setToken(String token){
        Token = token;
    }

    private String getToken(){
        return Token;
    }

    public static <T> void cancelCall(Call<T> call){
        if(call != null && call.isExecuted()){
            call.cancel();
        }
        call = null;
    }

    public static RequestBody getBodyByJson(Object object){
        String json = new Gson().toJson(object);
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), json);
        return body;
    }


    static class GzipRequestInterceptor implements Interceptor{
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
                return chain.proceed(originalRequest);
            }
            Request compressedRequest = originalRequest.newBuilder()
                    .header("Content-Encoding","gzip")
                    .method(originalRequest.method(),gzip(originalRequest.body()))
                    .build();
            return chain.proceed(compressedRequest);
        }
        private RequestBody gzip(final RequestBody body){
            return new RequestBody() {
                @Override
                public MediaType contentType() {
                    MyLog.D("gzip!");
                    return body.contentType();
                }
                @Override
                public long contentLength() throws IOException {
                    return -1;
                }
                @Override
                public void writeTo(BufferedSink sink) throws IOException {
                    BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
                    body.writeTo(gzipSink);
                    gzipSink.close();
                }
            };
        }
    }
}
